/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package wisimconsole;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JScrollBar;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import wiBase.WiException;
import wiBase.WiObject;
import wiBase.baseInterface.OnOutputStreamListener;
import wiBase.baseObject.Event;
import wiBase.baseObject.Node;
import wiBase.baseObject.Packet;
import wiModel.WiModelAdapter;

/**
 *
 * @author brother
 */
public class ConsoleFrame extends javax.swing.JFrame implements OnOutputStreamListener,wiEngine.WiEngine.OnEngineControlListener{

    private static final boolean DEBUG = true;
    private static final String SPEED_ODD_0001X = "0.001X";
    private static final String SPEED_ODD_001X = "0.01X";
    private static final String SPEED_ODD_01X = "0.1X";
    private static final String SPEED_ODD_02X = "0.2X";
    private static final String SPEED_ODD_03X = "0.3X";
    private static final String SPEED_ODD_04X = "0.4X";
    private static final String SPEED_ODD_05X = "0.5X";
    private static final String SPEED_1X = "1X";
    private static final String SPEED_2X = "2X";
    private static final String SPEED_3X = "3X";
    private static final String SPEED_4X = "4X";
    private static final String LBL_PLAY = "Play";
    private static final String LBL_PAUSE = "Pause";
    private static final String LBL_PLAYING = "Playing";
    private static final String LBL_PAUSING = "Pausing";
    private static final String LBL_PAUSED = "Paused";
    private static final String LBL_PARSE = "Parse";
    private static final String LBL_CANCEL = "Cancel";
    // config
    private boolean showGraphics;
    Color fgHlConsole = Color.YELLOW;
    Color fgConsole = Color.WHITE;
    Color bgConsole = Color.BLACK;
    WiSimConsole console = null;
    StringBuilder txtConsole = new StringBuilder();
    StringBuilder txtConsoleNode = new StringBuilder();
    StringBuilder txtConsolePacket = new StringBuilder();
    StringBuilder strConfig = new StringBuilder();
    String fileTracePath = "C:\\Users\\brother\\Desktop\\trace.tr";
    // Local variable
    FilterFrame mFilterFrame = null;
    InfoNodeFrame mInfoNodeFrame = null;
    InfoPacketFrame mInfoPacketFrame = null;
    JScrollBar scrVertical;
//    TwoTicksSlider slider;
    Thread tParse = null;
    Document doc = null;
    EditorKit kit;

    /**
     * Creates new form ConsoleFrame
     */
    public ConsoleFrame(WiSimConsole aThis) {
	this.console = aThis;
	initComponents();

	if (DEBUG) {
	    System.out.println("Console frame created");
	}

	mFilterFrame = new FilterFrame(console);
	mInfoNodeFrame = new InfoNodeFrame(console);
	mInfoPacketFrame = new InfoPacketFrame(console);

	scrVertical = jpn_console.getVerticalScrollBar();

	doc = txt_console.getDocument();
	txt_console.setDoubleBuffered(false);
	
	kit = txt_console.getEditorKit();

	jpn_slider.setLayout(new CardLayout());
//	sl_timer = new TwoTicksSlider(0, 100);
//	slider.addTwoChangeListener(new TwoTicksSlider.TwoTickListener() {
//	    @Override
//	    public void Tick1Clicked(ChangeEvent evt) {
//		TwoTicksSlider source = (TwoTicksSlider) evt.getSource();
//		lbl_time_from.setText(source.getValue() + "");
//	    }
//
//	    @Override
//	    public void Tick2Clicked(ChangeEvent evt) {
//		TwoTicksSlider source = (TwoTicksSlider) evt.getSource();
//		lbl_time_to.setText(source.getValue2() + "s");
//	    }
//
//	    @Override
//	    public void TickException(String message) {
//		setStatus(message);
//	    }
//	});
//	jpn_slider.add(slider);
//	jpn_slider.remove(sl_timer);
	setFont();
	refreshUI();
    }
    SimpleAttributeSet attDef = new SimpleAttributeSet();
    SimpleAttributeSet attType = new SimpleAttributeSet();
    SimpleAttributeSet attTime = new SimpleAttributeSet();
    SimpleAttributeSet attPacket = new SimpleAttributeSet();
    SimpleAttributeSet attNode = new SimpleAttributeSet();

    private void setFont() {
	int fontSizeDefault = 14;

	StyleConstants.setFontSize(attDef, fontSizeDefault);
	StyleConstants.setForeground(attDef, Color.white);

	StyleConstants.setFontSize(attType, fontSizeDefault);
	StyleConstants.setForeground(attType, Color.green);

	StyleConstants.setFontSize(attTime, fontSizeDefault);
	StyleConstants.setForeground(attTime, Color.yellow);

	StyleConstants.setFontSize(attPacket, fontSizeDefault);
	StyleConstants.setForeground(attPacket, Color.white);

	StyleConstants.setFontSize(attNode, fontSizeDefault);
	StyleConstants.setForeground(attNode, Color.yellow);
    }

    private void setEnableView(boolean when) {
	btn_browser.setEnabled(when);
	btn_play.setEnabled(when);
	btn_stop.setEnabled(when);
	cb_speed.setEnabled(when);
	sl_timer.setEnabled(when);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        fc_tracefilechooser = new javax.swing.JFileChooser();
        jpn_title = new javax.swing.JPanel();
        lbl_tracefile = new javax.swing.JLabel();
        btn_browser = new javax.swing.JButton();
        tf_search = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        lbl_help_search = new javax.swing.JLabel();
        jpn_console = new javax.swing.JScrollPane();
        txt_console = new javax.swing.JTextPane();
        jpn_status = new javax.swing.JPanel();
        lbl_status = new javax.swing.JLabel();
        pg_waiting = new javax.swing.JProgressBar();
        jpn_control = new javax.swing.JPanel();
        btn_play = new javax.swing.JToggleButton();
        btn_stop = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        cb_speed = new javax.swing.JComboBox();
        btn_parse = new javax.swing.JToggleButton();
        jpn_slider = new javax.swing.JPanel();
        sl_timer = new javax.swing.JSlider();
        jLabel3 = new javax.swing.JLabel();
        lbl_timer = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        lbl_time_to = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        lbl_time_from = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jpn_filter = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jl_filted_nodes = new javax.swing.JList();
        btn_filter_option = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jMenuBar1 = new javax.swing.JMenuBar();
        mn_file = new javax.swing.JMenu();
        mn_open = new javax.swing.JMenuItem();
        mn_close = new javax.swing.JMenuItem();
        mn_exit = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jCheckBoxMenuItem2 = new javax.swing.JCheckBoxMenuItem();
        mn_graphics = new javax.swing.JCheckBoxMenuItem();
        mn_view_filter_bar = new javax.swing.JCheckBoxMenuItem();
        cb_menu_controlbar = new javax.swing.JCheckBoxMenuItem();
        jCheckBoxMenuItem1 = new javax.swing.JCheckBoxMenuItem();
        cb_use_native = new javax.swing.JCheckBoxMenuItem();
        jMenu3 = new javax.swing.JMenu();
        mn_filter = new javax.swing.JMenu();
        mn_filter_table = new javax.swing.JMenuItem();
        jMenu1 = new javax.swing.JMenu();
        mn_info_node = new javax.swing.JMenuItem();
        mn_info_packet = new javax.swing.JMenuItem();
        mn_info_event = new javax.swing.JMenuItem();
        jMenuItem10 = new javax.swing.JMenuItem();
        jMenu5 = new javax.swing.JMenu();
        jMenuItem11 = new javax.swing.JMenuItem();
        jMenuItem12 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("WiSimulation Console");
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(670, 470));

        lbl_tracefile.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        lbl_tracefile.setText("C:\\Users\\brother\\Desktop\\trace.tr");
        lbl_tracefile.setToolTipText("File trace");

        btn_browser.setText("File:");
        btn_browser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_browserActionPerformed(evt);
            }
        });

        tf_search.setText("event");
        tf_search.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                tf_searchActionPerformed(evt);
            }
        });

        jLabel2.setText("Search:");

        lbl_help_search.setIcon(new javax.swing.ImageIcon(getClass().getResource("/image/help_1.jpg"))); // NOI18N
        lbl_help_search.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                lbl_help_searchMouseClicked(evt);
            }
        });

        javax.swing.GroupLayout jpn_titleLayout = new javax.swing.GroupLayout(jpn_title);
        jpn_title.setLayout(jpn_titleLayout);
        jpn_titleLayout.setHorizontalGroup(
            jpn_titleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_titleLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(btn_browser)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lbl_tracefile)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 221, Short.MAX_VALUE)
                .addComponent(lbl_help_search)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(tf_search, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        jpn_titleLayout.setVerticalGroup(
            jpn_titleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(lbl_help_search, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(jpn_titleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lbl_tracefile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(btn_browser)
                .addComponent(tf_search, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(jLabel2))
        );

        jpn_console.setBackground(new java.awt.Color(255, 153, 153));
        jpn_console.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        jpn_console.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        txt_console.setBackground(new java.awt.Color(0, 0, 0));
        txt_console.setForeground(new java.awt.Color(255, 255, 255));
        txt_console.setText("01: event time = 0.00001 send from 1 to 2\n02: event time = 0.00001 send from 1 to 2\n03: event time = 0.00001 send from 1 to 2\n04: event time = 0.00001 send from 1 to 2\n05: event time = 0.00001 send from 1 to 2\n06: event time = 0.00001 send from 1 to 2\n07: event time = 0.00001 send from 1 to 2\n08: event time = 0.00001 send from 1 to 2\n09: event time = 0.00001 send from 1 to 2\n10: event time = 0.00001 send from 1 to 2\n11: event time = 0.00001 send from 1 to 2\n12: event time = 0.00001 send from 1 to 2\n13: event time = 0.00001 send from 1 to 2\n14: event time = 0.00001 send from 1 to 2\n15: event time = 0.00001 send from 1 to 2\n16: event time = 0.00001 send from 1 to 2\n17: event time = 0.00001 send from 1 to 2\n18: event time = 0.00001 send from 1 to 2\n19: event time = 0.00001 send from 1 to 2\n20: event time = 0.00001 send from 1 to 2\n21: event time = 0.00001 send from 1 to 2\n22: event time = 0.00001 send from 1 to 2\n23: event time = 0.00001 send from 1 to 2\n24: event time = 0.00001 send from 1 to 2\n25: event time = 0.00001 send from 1 to 2\n26: event time = 0.00001 send from 1 to 2\n27: event time = 0.00001 send from 1 to 2\n28: event time = 0.00001 send from 1 to 2\n29: event time = 0.00001 send from 1 to 2\n30: event time = 0.00001 send from 1 to 2\n31: event time = 0.00001 send from 1 to 2\n32: event time = 0.00001 send from 1 to 2");
        txt_console.setCaretColor(new java.awt.Color(204, 255, 255));
        txt_console.setCaretPosition(0);
        txt_console.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
        txt_console.setDebugGraphicsOptions(javax.swing.DebugGraphics.NONE_OPTION);
        jpn_console.setViewportView(txt_console);
        jpn_console.setBackground(Color.BLACK);

        lbl_status.setText("Status:");

        pg_waiting.setValue(20);

        javax.swing.GroupLayout jpn_statusLayout = new javax.swing.GroupLayout(jpn_status);
        jpn_status.setLayout(jpn_statusLayout);
        jpn_statusLayout.setHorizontalGroup(
            jpn_statusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_statusLayout.createSequentialGroup()
                .addComponent(lbl_status, javax.swing.GroupLayout.DEFAULT_SIZE, 520, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pg_waiting, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        jpn_statusLayout.setVerticalGroup(
            jpn_statusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_statusLayout.createSequentialGroup()
                .addGroup(jpn_statusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(lbl_status, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(pg_waiting, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(0, 0, Short.MAX_VALUE))
        );

        btn_play.setText("Play");
        btn_play.setToolTipText("Start or pause simulation");
        btn_play.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_playActionPerformed(evt);
            }
        });

        btn_stop.setText("Stop");
        btn_stop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_stopActionPerformed(evt);
            }
        });

        jLabel1.setText("Speed");

        cb_speed.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "0.001X", "0.01X", "0.1X", "0.2X", "0.3X", "0.4X", "0.5X", "1X", "2X", "3X", "4X" }));
        cb_speed.setSelectedIndex(5);
        cb_speed.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cb_speedActionPerformed(evt);
            }
        });

        btn_parse.setText("Parse");
        btn_parse.setToolTipText("Start or pause simulation");
        btn_parse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_parseActionPerformed(evt);
            }
        });

        sl_timer.setForeground(new java.awt.Color(0, 0, 204));
        sl_timer.setMinorTickSpacing(1);
        sl_timer.setPaintLabels(true);
        sl_timer.setSnapToTicks(true);
        sl_timer.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sl_timerStateChanged(evt);
            }
        });

        javax.swing.GroupLayout jpn_sliderLayout = new javax.swing.GroupLayout(jpn_slider);
        jpn_slider.setLayout(jpn_sliderLayout);
        jpn_sliderLayout.setHorizontalGroup(
            jpn_sliderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jpn_sliderLayout.createSequentialGroup()
                .addComponent(sl_timer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        jpn_sliderLayout.setVerticalGroup(
            jpn_sliderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_sliderLayout.createSequentialGroup()
                .addComponent(sl_timer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 11, Short.MAX_VALUE))
        );

        //Create the label table
        //Hashtable labelTable = new Hashtable();
        //labelTable.put( new Integer( 0 ), new JLabel("Start") );
        //labelTable.put( new Integer( 10 ), new JLabel("10%") );
        //labelTable.put( new Integer( 20 ), new JLabel("20%") );
        //labelTable.put( new Integer( 50 ), new JLabel("50%") );
        //labelTable.put( new Integer( 100 ), new JLabel("Finish") );
        //sl_timer.setLabelTable( labelTable );
        //
        //sl_timer.setPaintLabels(true);

        //sl_timer.setUI(new MySliderUI(sl_timer));

        jLabel3.setText("Current Time:");

        lbl_timer.setText("00.000000");

        jLabel4.setText("second");

        lbl_time_to.setText("100%");

        jLabel5.setText("to:");

        lbl_time_from.setText("0%");

        jLabel7.setText("from:");

        javax.swing.GroupLayout jpn_controlLayout = new javax.swing.GroupLayout(jpn_control);
        jpn_control.setLayout(jpn_controlLayout);
        jpn_controlLayout.setHorizontalGroup(
            jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_controlLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jpn_slider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jpn_controlLayout.createSequentialGroup()
                        .addComponent(btn_parse, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(btn_play, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(btn_stop, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(cb_speed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jpn_controlLayout.createSequentialGroup()
                        .addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lbl_timer)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabel7)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lbl_time_from)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lbl_time_to)))
                .addContainerGap())
        );
        jpn_controlLayout.setVerticalGroup(
            jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_controlLayout.createSequentialGroup()
                .addGroup(jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(lbl_timer)
                        .addComponent(jLabel3)
                        .addComponent(jLabel4))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(lbl_time_to)
                        .addComponent(jLabel5)
                        .addComponent(lbl_time_from)
                        .addComponent(jLabel7)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jpn_slider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jpn_controlLayout.createSequentialGroup()
                        .addGroup(jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(btn_stop, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(btn_play, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(btn_parse, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(jpn_controlLayout.createSequentialGroup()
                        .addGroup(jpn_controlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(cb_speed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel1))
                        .addGap(0, 0, Short.MAX_VALUE))))
        );

        jpn_filter.setBorder(javax.swing.BorderFactory.createTitledBorder("Filter Option"));
        jpn_filter.setEnabled(false);

        jl_filted_nodes.setBorder(javax.swing.BorderFactory.createTitledBorder("Nodes"));
        jl_filted_nodes.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPane1.setViewportView(jl_filted_nodes);

        btn_filter_option.setText("Option");
        btn_filter_option.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_filter_optionActionPerformed(evt);
            }
        });

        jList1.setBorder(javax.swing.BorderFactory.createTitledBorder("Packets"));
        jList1.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList1.setToolTipText("");
        jScrollPane2.setViewportView(jList1);

        javax.swing.GroupLayout jpn_filterLayout = new javax.swing.GroupLayout(jpn_filter);
        jpn_filter.setLayout(jpn_filterLayout);
        jpn_filterLayout.setHorizontalGroup(
            jpn_filterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_filterLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(btn_filter_option)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(376, Short.MAX_VALUE))
        );
        jpn_filterLayout.setVerticalGroup(
            jpn_filterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpn_filterLayout.createSequentialGroup()
                .addComponent(btn_filter_option)
                .addGap(0, 84, Short.MAX_VALUE))
            .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
        );

        mn_file.setText("File");

        mn_open.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        mn_open.setText("Open trace file");
        mn_open.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mn_openActionPerformed(evt);
            }
        });
        mn_file.add(mn_open);

        mn_close.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, java.awt.event.InputEvent.CTRL_MASK));
        mn_close.setText("Close trace");
        mn_file.add(mn_close);

        mn_exit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.ALT_MASK));
        mn_exit.setText("Exit");
        mn_file.add(mn_exit);

        jMenuBar1.add(mn_file);

        jMenu2.setText("View");

        jCheckBoxMenuItem2.setSelected(true);
        jCheckBoxMenuItem2.setText("Header Bar");
        jCheckBoxMenuItem2.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jCheckBoxMenuItem2StateChanged(evt);
            }
        });
        jMenu2.add(jCheckBoxMenuItem2);

        mn_graphics.setText("Graphics");
        mn_graphics.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                mn_graphicsStateChanged(evt);
            }
        });
        jMenu2.add(mn_graphics);

        mn_view_filter_bar.setSelected(true);
        mn_view_filter_bar.setText("Filter Bar");
        mn_view_filter_bar.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                mn_view_filter_barStateChanged(evt);
            }
        });
        mn_view_filter_bar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mn_view_filter_barActionPerformed(evt);
            }
        });
        jMenu2.add(mn_view_filter_bar);

        cb_menu_controlbar.setSelected(true);
        cb_menu_controlbar.setText("Control Bar");
        cb_menu_controlbar.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                cb_menu_controlbarStateChanged(evt);
            }
        });
        cb_menu_controlbar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cb_menu_controlbarActionPerformed(evt);
            }
        });
        jMenu2.add(cb_menu_controlbar);

        jCheckBoxMenuItem1.setSelected(true);
        jCheckBoxMenuItem1.setText("Status Bar");
        jCheckBoxMenuItem1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jCheckBoxMenuItem1StateChanged(evt);
            }
        });
        jMenu2.add(jCheckBoxMenuItem1);

        cb_use_native.setText("Using Native");
        cb_use_native.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                cb_use_nativeStateChanged(evt);
            }
        });
        jMenu2.add(cb_use_native);

        jMenuBar1.add(jMenu2);

        jMenu3.setText("Tool");

        mn_filter.setText("Filter");

        mn_filter_table.setText("Open Filter Table");
        mn_filter_table.setEnabled(false);
        mn_filter_table.setName("mn_filter_table"); // NOI18N
        mn_filter_table.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mn_filter_tableActionPerformed(evt);
            }
        });
        mn_filter.add(mn_filter_table);

        jMenu3.add(mn_filter);

        jMenu1.setText("Get Info");

        mn_info_node.setText("Node");
        mn_info_node.setEnabled(false);
        mn_info_node.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mn_info_nodeActionPerformed(evt);
            }
        });
        jMenu1.add(mn_info_node);

        mn_info_packet.setText("Packet");
        mn_info_packet.setEnabled(false);
        mn_info_packet.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mn_info_packetActionPerformed(evt);
            }
        });
        jMenu1.add(mn_info_packet);

        mn_info_event.setText("Event");
        mn_info_event.setEnabled(false);
        jMenu1.add(mn_info_event);

        jMenu3.add(jMenu1);

        jMenuItem10.setText("Configuration");
        jMenu3.add(jMenuItem10);

        jMenuBar1.add(jMenu3);

        jMenu5.setText("Help");

        jMenuItem11.setText("How to?");
        jMenu5.add(jMenuItem11);

        jMenuItem12.setText("About");
        jMenu5.add(jMenuItem12);

        jMenuBar1.add(jMenu5);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jpn_console)
            .addComponent(jpn_status, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jpn_control, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jpn_title, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jpn_filter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jpn_title, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jpn_console, javax.swing.GroupLayout.DEFAULT_SIZE, 193, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jpn_filter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jpn_control, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jpn_status, javax.swing.GroupLayout.PREFERRED_SIZE, 13, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btn_browserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_browserActionPerformed
	openTraceFile();
    }//GEN-LAST:event_btn_browserActionPerformed

    private void openTraceFile() {
	fc_tracefilechooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
	if (fc_tracefilechooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
	    fileTracePath = fc_tracefilechooser.getSelectedFile().getAbsolutePath();
	    String traceFilePath = fileTracePath;
	    if (DEBUG) {
		System.out.print(traceFilePath);
	    }
	    int length = traceFilePath.length();
	    int maxLength = 50;
	    if (length > maxLength) {
		traceFilePath = "..." + traceFilePath.substring(length - maxLength, length);
	    }
	    lbl_tracefile.setText(traceFilePath);
	    setStatus("selected dir: " + traceFilePath);
	    refreshUI();
	}
    }

    private void mn_filter_tableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mn_filter_tableActionPerformed
	mFilterFrame.refreshData();
	mFilterFrame.setVisible(true);
    }//GEN-LAST:event_mn_filter_tableActionPerformed

    private void cb_menu_controlbarStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_cb_menu_controlbarStateChanged
	AbstractButton abstractButton = (AbstractButton) evt.getSource();
	ButtonModel buttonModel = abstractButton.getModel();
	boolean armed = buttonModel.isArmed();
	boolean pressed = buttonModel.isPressed();
	if (pressed) {
	    boolean selected = buttonModel.isSelected();
	    //System.out.println("Changed: " + armed + "/" + pressed + "/" + selected);
	    jpn_control.setVisible(selected);
	}
    }//GEN-LAST:event_cb_menu_controlbarStateChanged

    private void jCheckBoxMenuItem1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jCheckBoxMenuItem1StateChanged
	AbstractButton abstractButton = (AbstractButton) evt.getSource();
	ButtonModel buttonModel = abstractButton.getModel();
	boolean armed = buttonModel.isArmed();
	boolean pressed = buttonModel.isPressed();
	if (pressed) {
	    boolean selected = buttonModel.isSelected();
	    //System.out.println("Changed: " + armed + "/" + pressed + "/" + selected);
	    jpn_status.setVisible(selected);
	}
    }//GEN-LAST:event_jCheckBoxMenuItem1StateChanged

    private void jCheckBoxMenuItem2StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jCheckBoxMenuItem2StateChanged
	AbstractButton abstractButton = (AbstractButton) evt.getSource();
	ButtonModel buttonModel = abstractButton.getModel();
	boolean armed = buttonModel.isArmed();
	boolean pressed = buttonModel.isPressed();
	if (pressed) {
	    boolean selected = buttonModel.isSelected();
	    //System.out.println("Changed: " + armed + "/" + pressed + "/" + selected);
	    jpn_title.setVisible(selected);
	}
    }//GEN-LAST:event_jCheckBoxMenuItem2StateChanged

    private void btn_playActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_playActionPerformed
	if (!this.console.getEngine().isParsed()) {
	    strConfig = new StringBuilder("Need to parse file");
	    JOptionPane.showMessageDialog(this, "File trace must be trace first!", "Notice: Parse file", JOptionPane.INFORMATION_MESSAGE);
	    return;
	}
	// after parsed
	strConfig = new StringBuilder("Simulator file: " + fileTracePath);
	AbstractButton abstractButton = (AbstractButton) evt.getSource();
	ButtonModel buttonModel = abstractButton.getModel();
//	boolean armed = buttonModel.isArmed();
//	boolean pressed = buttonModel.isPressed();
	boolean selected = buttonModel.isSelected();

	removeHightLightColor();
	btn_play.setText(selected ? LBL_PAUSE : LBL_PLAY);
	setStatus(selected ? LBL_PLAYING : LBL_PAUSING);

	txt_console.setFocusable(!selected);
	mn_filter_table.setEnabled(!selected);
//	cb_speed.setEnabled(!selected);

	try {
	    Thread.sleep(0);
	} catch (InterruptedException ex) {
	}
//	if(isStopped){
//	    System.out.println("in here");
//	    
//	    play();
//	    return;
//	}
	if (selected) {
	    if (isPaused) {
		if (isStopped) {
		    System.out.println("in here2");
		    play();
		} else {
		    resume();
		}
	    } else {
		play();
	    }
	} else {
	    pause();
	}
    }//GEN-LAST:event_btn_playActionPerformed
    boolean isPaused = false;
    boolean isStopped = true;
    boolean isParsing = false;

    public void resume() {
	// resume
	isPaused = false;
	try {
	    this.console.getEngine().resume();
	} catch (WiException ex) {
	    System.out.println(ex.toString());
	}
    }

    public void play() {
//	slider.setMinimum(0);
//	slider.setMaximum((int)(console.getEngine().getAdapter().getDurationSimulation()*1E9));
	// start
	this.console.getEngine().setStartTime((int)(sl_timer.getValue()/1E3));
	System.out.println("set startTime: "+(int)(sl_timer.getValue()/1E3));
	this.console.getEngine().setEndTime((int)console.getEngine().getAdapter().getDurationSimulation());
	this.console.setTraceEvent();

//	    this.console.getGraphic().playGraph();
	this.console.getGraphic().setVisible(showGraphics);
	this.console.getEngine().run();
    }

    public void pause() {
	isPaused = true;

	console.getEngine().pause();
	setTextConsole(txtConsole);
    }

    public void stop() {
	isPaused = false;
	isStopped = true;
	btn_play.setSelected(false);

	txt_console.setFocusable(true);
	mn_filter_table.setEnabled(true);
	cb_speed.setEnabled(true);

	sl_timer.setValue(0);

	btn_play.setText(LBL_PLAY);
	setTextConsole(txtConsole);
	setStatus("Simulation Complete");
	try {
	    Thread.sleep(0);
	} catch (InterruptedException ex) {
	}
	try {
	    Thread.currentThread().sleep(0);
	    console.getEngine().stop();
	} catch (InterruptedException | WiException ex) {
	    setStatus("Sorry, Can not stop!");
	}
    }
//    public void play(boolean play) {
//	txt_console.setFocusable(!play);
//	mn_filter_table.setEnabled(!play);
//	cb_speed.setEnabled(!play);
//
//	if (play) {
//	    // resume
//	    if (isPaused) {
//		isPaused = false;
//		try {
//		    this.console.getEngine().resume();
//		} catch (WiException ex) {
//		    System.out.println(ex.toString());
//		}
//		return;
//	    }
//	    // start
//	    this.console.getEngine().setStartTime(slider.getValue());
//	    this.console.getEngine().setEndTime(slider.getValue2());
//	    this.console.setTraceEvent();
//
////	    this.console.getGraphic().playGraph();
//	    this.console.getGraphic().setVisible(showGraphics);
//	    this.console.getEngine().run();
//
//	} else {
//	    isPaused = true;
//
//	    this.console.getEngine().pause();
//	    setTextConsole(txtConsole);
//	}
//    }

    public void hightLightColor(Color color, String text, int position) throws IllegalArgumentException {

	StyleContext sc = StyleContext.getDefaultStyleContext();
	AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
		StyleConstants.Foreground, color);

	txt_console.setCaretPosition(position);  // place caret at the end (with no selection)
	txt_console.setCharacterAttributes(aset, false);
	txt_console.setSelectionStart(position);
	txt_console.setSelectionEnd(position + text.length());
	txt_console.replaceSelection(text); // there is no selection, so inserts at caret
    }

    public void removeHightLightColor() {
	try {
	    StyleContext sc = StyleContext.getDefaultStyleContext();
	    AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
		    StyleConstants.Foreground, fgConsole);
	    StringBuilder textAll = new StringBuilder(txt_console.getText().toString());
	    txt_console.setCaretPosition(0);  // place caret at the end (with no selection)
	    txt_console.setCharacterAttributes(aset, false);
	    txt_console.setSelectionStart(0);
	    txt_console.setSelectionEnd(txt_console.getText().length());
	    txt_console.replaceSelection(textAll.toString()); // there is no selection, so inserts at caret
	} catch (NullPointerException e) {
	}
    }

    private void mn_openActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mn_openActionPerformed
	openTraceFile();
    }//GEN-LAST:event_mn_openActionPerformed

    private void lbl_help_searchMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lbl_help_searchMouseClicked
	JOptionPane.showMessageDialog(this, "format: \n\t  TYPE VALUE\nExample: \n\t  'Node 1'\n\t  'Event send'", "How to search", JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_lbl_help_searchMouseClicked

    private void btn_stopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_stopActionPerformed
	stop();
    }//GEN-LAST:event_btn_stopActionPerformed

    private void tf_searchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tf_searchActionPerformed
	this.txt_console.setEditable(true);
	removeHightLightColor();
	String input = tf_search.getText();
	if (input.length() > 0) {
	    setStatus("Searching: '" + input + "'");
	    String docText = txt_console.getText();
	    int index = -1;
	    int counter = 0;
	    do {
		index = docText.indexOf(input, index + 1);
		try {
		    hightLightColor(this.fgHlConsole, input, index);
		    counter++;
		} catch (IllegalArgumentException e) {
		    //e.printStackTrace();
		}
	    } while (index >= 0);
	    if (counter >= 1) {
		setStatus("Searched: " + counter + " items for '" + input + "'");
	    } else {
		setStatus("no items for '" + input + "'");
	    }
	}
	this.txt_console.setEditable(false);
    }//GEN-LAST:event_tf_searchActionPerformed

    private void cb_menu_controlbarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cb_menu_controlbarActionPerformed
    }//GEN-LAST:event_cb_menu_controlbarActionPerformed

    private void mn_graphicsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_mn_graphicsStateChanged
	AbstractButton abstractButton = (AbstractButton) evt.getSource();
	ButtonModel buttonModel = abstractButton.getModel();
	boolean armed = buttonModel.isArmed();
	boolean pressed = buttonModel.isPressed();
	if (pressed) {
	    boolean selected = buttonModel.isSelected();
	    //System.out.println("Changed: " + armed + "/" + pressed + "/" + selected);
	    showGraphics = selected;
	    this.console.getGraphic().setVisible(showGraphics);
	}

    }//GEN-LAST:event_mn_graphicsStateChanged

    private void sl_timerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sl_timerStateChanged
	JSlider source = (JSlider) evt.getSource();
	lbl_time_to.setText(source.getValue() + "ms");
    }//GEN-LAST:event_sl_timerStateChanged

    private void btn_parseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_parseActionPerformed
	
	if (isParsing) {
	    btn_parse.setText(LBL_CANCEL);
	} else {
	    btn_parse.setText(LBL_PARSE);
	}
	parse(btn_parse.getText());
	txt_console.setEditable(false);
	mn_filter_table.setEnabled(true);
	mn_info_node.setEnabled(true);
	mn_info_event.setEnabled(true);
	mn_info_packet.setEnabled(true);
    }//GEN-LAST:event_btn_parseActionPerformed

    private void cb_speedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cb_speedActionPerformed
	JComboBox cb = (JComboBox) evt.getSource();
	String petName = (String) cb.getSelectedItem();
	switch (petName) {

	    case SPEED_ODD_0001X:
		this.console.getEngine().setSpeed(1D, TimeUnit.MICROSECONDS);
		break;
	    case SPEED_ODD_001X:
		this.console.getEngine().setSpeed(1/10D, TimeUnit.MICROSECONDS);
		break;
	    case SPEED_ODD_01X:
		this.console.getEngine().setSpeed(10/1D, TimeUnit.NANOSECONDS);
		break;
	    case SPEED_ODD_02X:
		this.console.getEngine().setSpeed(10/2D, TimeUnit.NANOSECONDS);
		break;
	    case SPEED_ODD_03X:
		this.console.getEngine().setSpeed(10/3D, TimeUnit.NANOSECONDS);
		break;
	    case SPEED_ODD_04X:
		this.console.getEngine().setSpeed(10/4D, TimeUnit.NANOSECONDS);
		break;
	    case SPEED_ODD_05X:
		this.console.getEngine().setSpeed(10/5D, TimeUnit.NANOSECONDS);
		break;
	    case SPEED_1X:
		this.console.getEngine().setSpeed(1D, TimeUnit.NANOSECONDS);
		break;
	    case SPEED_2X:
		this.console.getEngine().setSpeed(1 / 2D,TimeUnit.NANOSECONDS);
		break;
	    case SPEED_3X:
		this.console.getEngine().setSpeed(1 / 3D,TimeUnit.NANOSECONDS);
		break;
	    case SPEED_4X:
		this.console.getEngine().setSpeed(1 / 4D,TimeUnit.NANOSECONDS);
		break;
	}
	if (DEBUG) {
	    System.out.print(petName);
	}
    }//GEN-LAST:event_cb_speedActionPerformed

    private void mn_info_nodeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mn_info_nodeActionPerformed
	mInfoNodeFrame.setVisible(true);
    }//GEN-LAST:event_mn_info_nodeActionPerformed

    private void mn_info_packetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mn_info_packetActionPerformed
	mInfoPacketFrame.setVisible(true);
    }//GEN-LAST:event_mn_info_packetActionPerformed

    private void mn_view_filter_barActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mn_view_filter_barActionPerformed
    }//GEN-LAST:event_mn_view_filter_barActionPerformed

    private void mn_view_filter_barStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_mn_view_filter_barStateChanged
	AbstractButton abstractButton = (AbstractButton) evt.getSource();
	ButtonModel buttonModel = abstractButton.getModel();
	boolean armed = buttonModel.isArmed();
	boolean pressed = buttonModel.isPressed();
	if (pressed) {
	    boolean selected = buttonModel.isSelected();
	    //System.out.println("Changed: " + armed + "/" + pressed + "/" + selected);
	    jpn_filter.setVisible(selected);
	}
    }//GEN-LAST:event_mn_view_filter_barStateChanged

    private void btn_filter_optionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_filter_optionActionPerformed
	if (!this.console.getEngine().isParsed()) {
	    strConfig = new StringBuilder("Need to parse file");
	    JOptionPane.showMessageDialog(this, "File trace must be trace first!", "Notice: Parse file", JOptionPane.INFORMATION_MESSAGE);
	    return;
	}
	mFilterFrame.refreshData();
	mFilterFrame.setVisible(true);
    }//GEN-LAST:event_btn_filter_optionActionPerformed

    private void cb_use_nativeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_cb_use_nativeStateChanged
	AbstractButton abstractButton = (AbstractButton) evt.getSource();
	ButtonModel buttonModel = abstractButton.getModel();
	boolean armed = buttonModel.isArmed();
	boolean pressed = buttonModel.isPressed();
	if (pressed) {
	    boolean selected = buttonModel.isSelected();
	    //System.out.println("Changed: " + armed + "/" + pressed + "/" + selected);
	    console.getEngine().setNative(selected);
	}
    }//GEN-LAST:event_cb_use_nativeStateChanged

    public void parse(String btnParseLabel) {
	switch (btnParseLabel) {
	    case LBL_PARSE:
		txtConsole = new StringBuilder();
		this.console.getEngine().getAdapter().copyData();
		tParse = new Thread() {
		    @Override
		    public void run() {
			try {
			    setStatus("parsing: " + fileTracePath);
			    ConsoleFrame.this.jpn_control.setEnabled(false);
			    isParsing = true;
			    btn_parse.setText(LBL_CANCEL);
			    setEnableView(!isParsing);
			    try {
				Thread.sleep(0);
				ConsoleFrame.this.console.getEngine().setTraceFile(fileTracePath);
				console.getGraphic().Parse();
//				ConsoleFrame.this.console.parse();
				setStatus("parsed: " + fileTracePath + " in " + console.getEngine().getAdapter().getMilliTimeParse() + " ms");
//				slider.setMaximum((int) (console.getEngine().getAdapter().getDurationSimulation()*1E9));
				setEnablePanelFilter(true);
			    } catch (InterruptedException ex) {
				setStatus(ex.toString());
				setEnablePanelFilter(false);
			    }
			} finally {
			    ConsoleFrame.this.jpn_control.setEnabled(true);
			    isParsing = false;
			    isPaused = false;
			    isStopped = true;
			    btn_parse.setText(LBL_PARSE);
			    setEnableView(!isParsing);

			    setTextFormatParse();
			}
		    }
		};
		tParse.start();
		break;
	    case LBL_CANCEL:
		System.out.println("cancel");
		btn_parse.setText(LBL_PARSE);
		if (tParse != null && !tParse.isInterrupted()) {
		    tParse.interrupt();
		    setEnableView(true);
		}

		try {
		    this.console.getEngine().getAdapter().cancelParse();
		} catch (WiException ex) {
		}
		setEnablePanelFilter(false);
		break;
	}
    }

    private void setEnablePanelFilter(boolean enable) {
	jpn_filter.setEnabled(enable);

    }

    private void setStatus(String status) {
	lbl_status.setText(status);
    }

    private void refreshUI() {
	showGraphics = mn_graphics.isSelected();
	btn_play.setSelected(false);
	btn_play.setText(LBL_PLAY);
	txt_console.setText("trace file: " + fileTracePath);
    }

    public boolean isShowGraphics() {
	return showGraphics;
    }

    private void setTextConsole(StringBuilder text) {
	try {
	    if (doc == null) {
		return;
	    }
	    doc.insertString(0, "", attDef);
	    doc.remove(0, doc.getLength());
	    if (text != null && text.length() != 0) {
		Reader r = new StringReader(text.toString());

		kit.read(r, doc, 0);
	    }
	} catch (IOException | BadLocationException ex) {
	}

    }
    static StringBuilder builder=new StringBuilder();
    private void setTextFormat(WiObject object) {
	boolean draw=true;
	if(!draw) return;
	if (object instanceof Event) {
	    if (((Event) object).time.equals(this.console.getEngine().getAdapter().getDurationSimulation() + "")) {
		stop();
	    }
	    try {		
		doc.remove(0, doc.getLength());
		doc.insertString(doc.getLength(), object.toString(), attType);
		
//		builder=new StringBuilder("Type:\t " + ((Event) object).type + "\n");
//		doc.insertString(doc.getLength(), builder.toString(), attType);
//		builder=new StringBuilder("Time:\t " + ((Event) object).time + "\n");
//		doc.insertString(doc.getLength(), builder.toString(), attTime);
//		builder=new StringBuilder("Packet Id:\t " + ((Event) object).packetId + "\n");
//		doc.insertString(doc.getLength(), builder.toString(), attPacket);
//		builder=new StringBuilder("-----------Event Info----------" + "\n");
//		doc.insertString(doc.getLength(), builder.toString(), attDef);
//		builder=new StringBuilder("Event: " + ((Event) object).toString(true));
//		doc.insertString(doc.getLength(), builder.toString(), attDef);

	    } catch (BadLocationException ex) {
	    }
	}

    }

    private void setTextFormatParse() {
	WiModelAdapter adapter = this.console.getEngine().getAdapter();
	String fileTrace = adapter.getFileTrace();
	String fileConf = adapter.getFileConfig();
	String duration = adapter.getDurationSimulation() + "";
	String width = adapter.getWidth() + "";
	String timeParse = adapter.getMilliTimeParse() + "";
	String length = adapter.getLength() + "";

	lbl_time_from.setText("0");

	lbl_time_to.setText(String.valueOf(adapter.getDurationSimulation()));
//	slider.setMaximum((int) (adapter.getDurationSimulation()*1E9));
	this.console.getEngine().setStartTime(-1);
	this.console.getEngine().setEndTime((long) adapter.getDurationSimulation());


	try {
	    doc.remove(0, doc.getLength());
	    doc.insertString(doc.getLength(), "File trace:\t " + fileTrace + "\n", attType);
	    doc.insertString(doc.getLength(), "File config:\t " + fileConf + "\n", attTime);
	    doc.insertString(doc.getLength(), "Duration:\t " + duration + "\n", attPacket);
	    doc.insertString(doc.getLength(), "Width:\t " + width + "\n", attTime);
	    doc.insertString(doc.getLength(), "Time parse:\t " + timeParse + "\n", attPacket);
	    doc.insertString(doc.getLength(), "Length:\t " + length + "\n", attTime);
	    doc.insertString(doc.getLength(), "-----------Parse File Complete----------" + "\n", attDef);

	} catch (BadLocationException ex) {
	    ex.printStackTrace();
	}
    }

    @Override
    public void write(String type, WiObject... seriable) {
	if (seriable[0] instanceof Event) {

	    if (((Event) seriable[0]).type.equals("end")) {
		stop();
		if(DEBUG){
		    System.out.println("stop simulation");
		}
		return;
	    }
	    try {
		txtConsole.append("\n").append(seriable[0].toString());

		setTextFormat(seriable[0]);

		long time = ((Event) seriable[0]).getTime() / (long) 1E9;

		scrVertical.setValue(scrVertical.getMaximum());
		lbl_timer.setText(time + "");
		Thread.sleep(0);
	    } catch (NullPointerException | InterruptedException | ArrayIndexOutOfBoundsException e) {
		System.out.println(e.toString());
	    }

	} else {
	    //System.out.println(seriable[0].toString());
	}
	if (seriable.length > 1) {
	    if (seriable[1] instanceof Node) {
		//System.out.println(seriable[1].toString());
		txtConsole.append("\n").append(seriable[1].toString());
	    } else if (seriable[1] instanceof Packet) {
		//System.out.println(seriable[1].toString());
		txtConsole.append("\n").append(seriable[1].toString());
	    } else {
		//System.out.println(seriable[1].toString());
	    }
	}

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
	/* Set the Nimbus look and feel */
	//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
	 * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
	 */
	try {
	    for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
		if ("Nimbus".equals(info.getName())) {
		    javax.swing.UIManager.setLookAndFeel(info.getClassName());
		    break;
		}
	    }
	} catch (ClassNotFoundException ex) {
	    java.util.logging.Logger.getLogger(ConsoleFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
	} catch (InstantiationException ex) {
	    java.util.logging.Logger.getLogger(ConsoleFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
	} catch (IllegalAccessException ex) {
	    java.util.logging.Logger.getLogger(ConsoleFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
	} catch (javax.swing.UnsupportedLookAndFeelException ex) {
	    java.util.logging.Logger.getLogger(ConsoleFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
	}
	//</editor-fold>

	/* Create and display the form */
	java.awt.EventQueue.invokeLater(new Runnable() {
	    public void run() {
		new ConsoleFrame(null).setVisible(true);
	    }
	});
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btn_browser;
    private javax.swing.JButton btn_filter_option;
    private javax.swing.JToggleButton btn_parse;
    private javax.swing.JToggleButton btn_play;
    private javax.swing.JButton btn_stop;
    private javax.swing.JCheckBoxMenuItem cb_menu_controlbar;
    private javax.swing.JComboBox cb_speed;
    private javax.swing.JCheckBoxMenuItem cb_use_native;
    private javax.swing.JFileChooser fc_tracefilechooser;
    private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem1;
    private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JList jList1;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenu jMenu5;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem10;
    private javax.swing.JMenuItem jMenuItem11;
    private javax.swing.JMenuItem jMenuItem12;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JList jl_filted_nodes;
    private javax.swing.JScrollPane jpn_console;
    private javax.swing.JPanel jpn_control;
    private javax.swing.JPanel jpn_filter;
    private javax.swing.JPanel jpn_slider;
    private javax.swing.JPanel jpn_status;
    private javax.swing.JPanel jpn_title;
    private javax.swing.JLabel lbl_help_search;
    private javax.swing.JLabel lbl_status;
    private javax.swing.JLabel lbl_time_from;
    private javax.swing.JLabel lbl_time_to;
    private javax.swing.JLabel lbl_timer;
    private javax.swing.JLabel lbl_tracefile;
    private javax.swing.JMenuItem mn_close;
    private javax.swing.JMenuItem mn_exit;
    private javax.swing.JMenu mn_file;
    private javax.swing.JMenu mn_filter;
    private javax.swing.JMenuItem mn_filter_table;
    private javax.swing.JCheckBoxMenuItem mn_graphics;
    private javax.swing.JMenuItem mn_info_event;
    private javax.swing.JMenuItem mn_info_node;
    private javax.swing.JMenuItem mn_info_packet;
    private javax.swing.JMenuItem mn_open;
    private javax.swing.JCheckBoxMenuItem mn_view_filter_bar;
    private javax.swing.JProgressBar pg_waiting;
    private javax.swing.JSlider sl_timer;
    private javax.swing.JTextField tf_search;
    private javax.swing.JTextPane txt_console;
    // End of variables declaration//GEN-END:variables

    @Override
    public void onTraceFileChange(String traceFile) {
	System.out.println("trace file change: "+traceFile);
	lbl_tracefile.setText(traceFile);
    }

    @Override
    public void onRun(long startTimeSecond, long endTimeSecond) {
	System.out.println("start Time: "+startTimeSecond);
    }

    @Override
    public void onPause() {
	System.out.println("pause");
    }

    @Override
    public void onResume() {
	System.out.println("resume");
    }

    @Override
    public void onStop() {
	System.out.println("stop");
    }

    @Override
    public void onSpeedChange(double speed, TimeUnit timeunit) {
	System.out.println(speed+timeunit.toString());
    }

    @Override
    public void onBeforeParse() {
	System.out.println("before parse");
    }

    @Override
    public void onAfterParse(long timeParse) {
	System.out.println("time parse: "+timeParse);
	//
	sl_timer.setMinimum(0);
	sl_timer.setMaximum((int)(console.getEngine().getAdapter().getDurationSimulation()*1E3));
    }

    @Override
    public void onRunTimeChange(long startTimeSecond, long finishTimeSecond) {
	System.out.println(startTimeSecond+"-"+finishTimeSecond);
    }

    @Override
    public void onNotification(Object... text) {
//	JOptionPane.showConfirmDialog(this, text[0].toString());
    }

    @Override
    public void onUpdateCurrentTime(long startTime9E,long finishTime9E,long currentTime9E) {
	sl_timer.setValue((int)(currentTime9E/1E6));
	try {
	    Thread.sleep(0,0);
	} catch (InterruptedException ex) {
	}
    }
    
    
}
